﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Common
{
    public static class DateOperation
    {
        /// <summary>
        /// 判断是不是周末/节假日
        /// </summary>
        /// <param name="date">日期</param>
        /// <returns>周末和节假日返回true，工作日返回false</returns>
        public static async Task<bool> IsHolidayByDate(DateTime date)
        {
            var isHoliday = false;
            var webClient = new System.Net.WebClient();
            var PostVars = new System.Collections.Specialized.NameValueCollection
            {
                { "d", date.ToString("yyyyMMdd") }//参数
            };
            try
            {
                var day = date.DayOfWeek;

                //判断是否为周末
                if (day == DayOfWeek.Sunday || day == DayOfWeek.Saturday)
                    return true;

                //0为工作日，1为周末，2为法定节假日
                var byteResult = await webClient.UploadValuesTaskAsync("http://tool.bitefu.net/jiari/", "POST", PostVars);//请求地址,传参方式,参数集合
                var result = Encoding.UTF8.GetString(byteResult);//获取返回值
                if (result == "1" || result == "2")
                    isHoliday = true;
            }
            catch
            {
                isHoliday = false;
            }
            return isHoliday;
        }

        /// <summary>
        /// 计算两个时间差，只计算周一到周五，去除周末
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public static int GetWorkDays(DateTime start, DateTime end)
        {
            if (string.IsNullOrEmpty(start.ToString()) || string.IsNullOrEmpty(end.ToString())) return 0;
            TimeSpan span = end - start;
            int AllDays = Convert.ToInt32(span.TotalDays) + 1;//差距的所有天数
            int totleWeek = AllDays / 7;//差别多少周
            int yuDay = AllDays % 7; //除了整个星期的天数
            int lastDay = 0;
            if (yuDay == 0) //正好整个周
            {
                lastDay = AllDays - (totleWeek * 2);
            }
            else
            {
                int yu_day = 0;
                for (var i = 0; i < yuDay; i++)
                {
                    DateTime newDay = end.AddDays(-i);
                    if (newDay.DayOfWeek == DayOfWeek.Saturday || newDay.DayOfWeek == DayOfWeek.Sunday)
                        yu_day += 1;
                }
                lastDay = AllDays - (totleWeek * 2) - yu_day;
            }
            
           return lastDay;
        }

        /// <summary>
        /// 获取日期对应星期
        /// </summary>
        /// <param name="time">日期</param>
        /// <returns></returns>
        public static string validateWeek(DateTime time)
        {
            string week = "";
            string dt = time.DayOfWeek.ToString();
            switch (dt)
            {
                case "Monday":
                    week = "一";
                    break;
                case "Tuesday":
                    week = "二";
                    break;
                case "Wednesday":
                    week = "三";
                    break;
                case "Thursday":
                    week = "四";
                    break;
                case "Friday":
                    week = "五";
                    break;
                case "Saturday":
                    week = "六";
                    break;
                case "Sunday":
                    week = "日";
                    break;
            }
            return week;
        }

        /// <summary>
        /// 判断两个时间范围是否有交集
        /// </summary>
        /// <param name="dynaStartTime">比较时间段开始时间</param>
        /// <param name="dynaEndTime">比较时间段结束时间</param>
        /// <param name="fixedStartTime">参考时间段开始时间</param>
        /// <param name="fixedEndTime">参考时间段结束时间</param>
        /// <returns></returns>
        public static Boolean checkTimesHasOverlap(DateTime dynaStartTime, DateTime dynaEndTime, DateTime fixedStartTime, DateTime fixedEndTime)
        {
            return !(dynaEndTime < fixedStartTime || dynaStartTime> fixedEndTime);
        }

        /// <summary>
        /// 获取两个时间段的重复部分
        /// </summary>
        /// <param name="startTime1">时间段1 开始 新入库数据的开始时间</param>
        /// <param name="endTime1">时间段1 结束 新入库数据的结束时间</param>
        /// <param name="startTime2">时间段2 取出数据的开始时间</param>
        /// <param name="endTime2">时间段2 结束 取出数据的结束时间</param>
        public static DateTime? GetDataOverTime(DateTime startTime1, DateTime endTime1, DateTime startTime2, DateTime endTime2)
        {

            TimeSpan RtnTs = new TimeSpan();
            ///重叠部分开始
            DateTime OverlapBegin;
            //重叠部分结束
            DateTime OverlapEnd;
            DateTime? lasttime=DateTime.Now;

            try
            {

                //情况一
                //       |-----------startTime1-----endTime1-----------|
                //          |--------startTime2-----endTime2-------|
                if (startTime1 <= startTime2 && endTime1 >= endTime2)
                {
                    OverlapBegin = startTime2;
                    OverlapEnd = endTime2;
                    RtnTs = endTime2 - startTime2;
                    lasttime = endTime1.AddMinutes(RtnTs.TotalMinutes);
                }

                //情况二
                //    |--------------startTime2-----endTime2----------------|
                //       |-----------startTime1-----endTime1-----------|
                else if (startTime1 >= startTime2 && endTime1 <= endTime2)
                {
                    OverlapBegin = startTime1;
                    OverlapEnd = endTime1;
                    RtnTs = endTime1 - startTime1;
                    lasttime = endTime2.AddMinutes(RtnTs.TotalMinutes);
                }

                //情况三
                //    |--------------startTime2-----endTime2----------------|
                //       |-----------startTime1-----endTime1----------------------|
                else if ((startTime2 <= startTime1 && startTime1 <= endTime2) && endTime1 >= endTime2)
                {
                    OverlapBegin = startTime1;
                    OverlapEnd = endTime2;
                    RtnTs = endTime2 - startTime1;
                    lasttime = endTime1.AddMinutes(RtnTs.TotalMinutes);
                }
                //情况四
                //    |--------------startTime1-----endTime1----------------|
                //       |-----------startTime2-----endTime2----------------------|
                else if ((startTime1 <= startTime2 && startTime2 <= endTime1) && endTime2 >= endTime1)
                {
                    OverlapBegin = startTime2;
                    OverlapEnd = endTime1;
                    RtnTs = endTime1 - startTime2;
                    lasttime = endTime2.AddMinutes(RtnTs.TotalMinutes);
                }
            }
            catch (Exception)
            {

                throw;
            }

            return lasttime;
        }


        /// <summary>
        /// 获取两个时间段的重复部分的时间戳值
        /// </summary>
        /// <param name="startTime1">时间段1 开始 新入库数据的开始时间</param>
        /// <param name="endTime1">时间段1 结束 新入库数据的结束时间</param>
        /// <param name="startTime2">时间段2 取出数据的开始时间</param>
        /// <param name="endTime2">时间段2 结束 取出数据的结束时间</param>
        public static TimeSpan GetDataOverTimeSpan(DateTime startTime1, DateTime endTime1, DateTime startTime2, DateTime endTime2)
        {

            TimeSpan RtnTs = new TimeSpan();
            ///重叠部分开始
            DateTime OverlapBegin;
            //重叠部分结束
            DateTime OverlapEnd;
            DateTime? lasttime = DateTime.Now;

            try
            {

                //情况一
                //       |-----------startTime1-----endTime1-----------|
                //          |--------startTime2-----endTime2-------|
                //新入的时间占用完就时间，并且超出了一部分，只有当新入时间结束，旧的时间才会重新开始 
                if (startTime1 <= startTime2 && endTime1 >= endTime2)
                {
                    OverlapBegin = startTime2;
                    OverlapEnd = endTime2;
                    RtnTs = endTime2 - startTime2;
                    //lasttime = endTime1.AddMinutes(RtnTs.TotalMinutes);
                }

                //情况二
                //    |--------------startTime2-----endTime2----------------|
                //       |-----------startTime1-----endTime1-----------|
                else if (startTime1 >= startTime2 && endTime1 <= endTime2)
                {
                    OverlapBegin = startTime1;
                    OverlapEnd = endTime1;
                    RtnTs = endTime1 - startTime1;
                    //lasttime = endTime2.AddMinutes(RtnTs.TotalMinutes);
                }

                //情况三
                //    |--------------startTime2-----endTime2----------------|
                //       |-----------startTime1-----endTime1----------------------|
                else if ((startTime2 <= startTime1 && startTime1 <= endTime2) && endTime1 >= endTime2)
                {
                    OverlapBegin = startTime1;
                    OverlapEnd = endTime2;
                    RtnTs = endTime2 - startTime1;
                    //lasttime = endTime1.AddMinutes(RtnTs.TotalMinutes);
                }
                //情况四
                //    |--------------startTime1-----endTime1----------------|
                //       |-----------startTime2-----endTime2----------------------|
                else if ((startTime1 <= startTime2 && startTime2 <= endTime1) && endTime2 >= endTime1)
                {
                    OverlapBegin = startTime2;
                    OverlapEnd = endTime1;
                    RtnTs = endTime1 - startTime2;
                    //lasttime = endTime2.AddMinutes(RtnTs.TotalMinutes);
                }
            }
            catch (Exception)
            {

                throw;
            }

            return RtnTs;
        }

        /// <summary>
        /// 获取两个时间段的重复部分的开始时间和结束时间
        /// </summary>
        /// <param name="startTime1">时间段1 开始 新入库数据的开始时间</param>
        /// <param name="endTime1">时间段1 结束 新入库数据的结束时间</param>
        /// <param name="startTime2">时间段2 取出数据的开始时间</param>
        /// <param name="endTime2">时间段2 结束 取出数据的结束时间</param>
        public static void GetDateTime(DateTime startTime1, DateTime endTime1, DateTime startTime2, DateTime endTime2,out DateTime startTime,out DateTime endTime)
        {

            TimeSpan RtnTs = new TimeSpan();
            ///重叠部分开始
            DateTime OverlapBegin = new DateTime();
            //重叠部分结束
            DateTime OverlapEnd = new DateTime();
            //DateTime? lasttime = DateTime.Now;

            try
            {

                //情况一
                //       |-----------startTime1-----endTime1-----------|
                //          |--------startTime2-----endTime2-------|
                //新入的时间占用完就时间，并且超出了一部分，只有当新入时间结束，旧的时间才会重新开始 
                if (startTime1 <= startTime2 && endTime1 >= endTime2)
                {
                    OverlapBegin = startTime2;
                    OverlapEnd = endTime2;
                    RtnTs = endTime2 - startTime2;
                    //lasttime = endTime1.AddMinutes(RtnTs.TotalMinutes);
                }

                //情况二
                //    |--------------startTime2-----endTime2----------------|
                //       |-----------startTime1-----endTime1-----------|
                else if (startTime1 >= startTime2 && endTime1 <= endTime2)
                {
                    OverlapBegin = startTime1;
                    OverlapEnd = endTime1;
                    RtnTs = endTime1 - startTime1;
                    //lasttime = endTime2.AddMinutes(RtnTs.TotalMinutes);
                }

                //情况三
                //    |--------------startTime2-----endTime2----------------|
                //       |-----------startTime1-----endTime1----------------------|
                else if ((startTime2 <= startTime1 && startTime1 <= endTime2) && endTime1 >= endTime2)
                {
                    OverlapBegin = startTime1;
                    OverlapEnd = endTime2;
                    RtnTs = endTime2 - startTime1;
                    //lasttime = endTime1.AddMinutes(RtnTs.TotalMinutes);
                }
                //情况四
                //    |--------------startTime1-----endTime1----------------|
                //       |-----------startTime2-----endTime2----------------------|
                else if ((startTime1 <= startTime2 && startTime2 <= endTime1) && endTime2 >= endTime1)
                {
                    OverlapBegin = startTime2;
                    OverlapEnd = endTime1;
                    RtnTs = endTime1 - startTime2;
                    //lasttime = endTime2.AddMinutes(RtnTs.TotalMinutes);
                }
            }
            catch (Exception)
            {

                throw;
            }

            startTime = OverlapBegin;
            endTime = OverlapEnd;
        }

        /// <summary>
        /// 计算两个时间差，计算出周末的时长
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public static int GetWeekDays(DateTime start, DateTime end)
        {
            if (string.IsNullOrEmpty(start.ToString()) || string.IsNullOrEmpty(end.ToString())) return 0;
            TimeSpan span = end - start;
            int AllDays = Convert.ToInt32(span.TotalDays) + 1;//差距的所有天数
            int totleWeek = AllDays / 7;//差别多少周
            int yuDay = AllDays % 7; //除了整个星期的天数
            int lastDay = 0;
            if (yuDay == 0) //正好整个周
            {
                lastDay = (totleWeek * 2);
            }
            else
            {
                int yu_day = 0;
                for (var i = 0; i < yuDay; i++)
                {
                    DateTime newDay = end.AddDays(-i);
                    if (newDay.DayOfWeek == DayOfWeek.Saturday || newDay.DayOfWeek == DayOfWeek.Sunday)
                        yu_day += 1;
                }
                lastDay = (totleWeek * 2) + yu_day;
            }

            return lastDay;
        }

        /// <summary>
        /// 计算出时间的周一到周五的list
        /// </summary>
        /// <param name="time">开始计算时间</param>
        /// <param name="days">天数</param>
        /// <returns></returns>
        public static List<DateTime?> GetWorkList(DateTime time,int days)
        {
            List<DateTime?> list = new List<DateTime?>();
            for (var i = 0; i < days; i++)
            {
                DateTime newDay = time.AddDays(i);
                if (newDay.DayOfWeek != DayOfWeek.Saturday && newDay.DayOfWeek != DayOfWeek.Sunday)
                {
                    list.Add(newDay);
                }
                else days++;
                    
            }
            return list;
        }

        /// <summary>
        /// 获取有重叠部分的两个时间段，最终返回去重的开始时间和结束时间
        /// </summary>
        /// <param name="startTime1">时间段1 开始 新入库数据的开始时间</param>
        /// <param name="endTime1">时间段1 结束 新入库数据的结束时间</param>
        /// <param name="startTime2">时间段2 取出数据的开始时间</param>
        /// <param name="endTime2">时间段2 结束 取出数据的结束时间</param>
        public static void GetAllDateTime(DateTime startTime1, DateTime endTime1, DateTime startTime2, DateTime endTime2, out DateTime MinStartTime, out DateTime MaxEndTime)
        {

            TimeSpan RtnTs = new TimeSpan();
            ///重叠部分开始
            DateTime OverlapBegin = new DateTime();
            //重叠部分结束
            DateTime OverlapEnd = new DateTime();
            //DateTime? lasttime = DateTime.Now;

            try
            {

                //情况一
                //       |-----------startTime1-----endTime1-----------|
                //          |--------startTime2-----endTime2-------|
                //新入的时间占用完就时间，并且超出了一部分，只有当新入时间结束，旧的时间才会重新开始 
                if (startTime1 <= startTime2 && endTime1 >= endTime2)
                {
                    OverlapBegin = startTime1;
                    OverlapEnd = endTime1;
                     
                }

                //情况二
                //    |--------------startTime2-----endTime2----------------|
                //       |-----------startTime1-----endTime1-----------|
                else if (startTime1 >= startTime2 && endTime1 <= endTime2)
                {
                    OverlapBegin = startTime2;
                    OverlapEnd = endTime2;
                    
                }

                //情况三
                //    |--------------startTime2-----endTime2----------------|
                //       |-----------startTime1-----endTime1----------------------|
                else if ((startTime2 <= startTime1 && startTime1 <= endTime2) && endTime1 >= endTime2)
                {
                    OverlapBegin = startTime2;
                    OverlapEnd = endTime1;
                     
                }
                //情况四
                //    |--------------startTime1-----endTime1----------------|
                //       |-----------startTime2-----endTime2----------------------|
                else if ((startTime1 <= startTime2 && startTime2 <= endTime1) && endTime2 >= endTime1)
                {
                    OverlapBegin = startTime1;
                    OverlapEnd = endTime2;
                    
                }
            }
            catch (Exception)
            {

                throw;
            }

            MinStartTime = OverlapBegin;
            MaxEndTime = OverlapEnd;
        }

        /// <summary>
        /// 判断两个时间是否有重叠
        /// </summary>
        /// <param name="startTime1">时间段1 开始 新入库数据的开始时间</param>
        /// <param name="endTime1">时间段1 结束 新入库数据的结束时间</param>
        /// <param name="startTime2">时间段2 取出数据的开始时间</param>
        /// <param name="endTime2">时间段2 结束 取出数据的结束时间</param>
        public static bool isOverlap(DateTime startTime1, DateTime endTime1, DateTime startTime2, DateTime endTime2)
        {
            bool flag = true;
            //情况一
            //       |-----------startTime1-----endTime1-----------| |--------startTime2-----endTime2-------|
            //          
            if (endTime1 <= startTime2) flag = false;
            //情况一
            //       |--------startTime2-----endTime2-------||-----------startTime1-----endTime1-----------| 
            //   
            else if (endTime2 <= startTime1) flag = false;
            return flag;
        }
    }
}
